package com.zzh.partnersys.job;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zzh.partnersys.entity.UserDO;
import com.zzh.partnersys.entity.UserTeamDO;
import com.zzh.partnersys.mapper.TeamMapper;
import com.zzh.partnersys.mapper.UserMapper;
import com.zzh.partnersys.mapper.UserTeamMapper;
import com.zzh.partnersys.service.UserService;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import jakarta.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.zzh.partnersys.chat.cache.NettyCache.ID_TEAM_MAP;
import static com.zzh.partnersys.constant.UserConstant.*;


/**
 * @author ??????
 * @version 1.0
 * ��ʱ����??
 */
@Component
@Slf4j
public class JobSchedule {

    @Resource
    private UserMapper userMapper;

    @Resource
    private UserTeamMapper userTeamMapper;

    @Resource
    private TeamMapper teamMapper;

    @Autowired
    private UserService userService;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private RedissonClient redissonClient;

    /**
     * ��ʱ����1 : �Ƽ��û��б��redisԤ��
     * Ԥ�Ȳ������ж�Ԥ�ȵģ�������һ���ĸ߷�����/�ص��û�
     * Ԥ�ȵ��ٶ�Ҳ��Ҫ������ʱ������ʱ�䣡??
     */
//    @Scheduled(cron = "0 00 23 * * ?")//ÿ������17:15����
    public void doRecommendUserList(){

        RLock lock = redissonClient.getLock(USER_LOCK_JOB_RECOMMEND_KEY);
        try {
            //1.��ֻ֤��һ���߳��õ���
            if(lock.tryLock(0,30000L,TimeUnit.MILLISECONDS)){
                //����ǰ����Ϊ�Լ��ļ�����
                //����id��һ������ķ�ҳ��¼��һ������֤��ͬ�û������Ƽ����û������Լ���??
                for (int i = 1; i <=5; i++) {//ǰ����û���id = limit =>limit = 1 �����ѯ���Լ�����id=2��????
                    List<UserDO> userDOList = userMapper.customPaginationQuery(i, 20);
                    List<UserDO> safetyUserListDO = userDOList.stream().map(user -> userService.getSafeUser(user)).collect(Collectors.toList());
                    //���ݵ�ǰ�û�id����??��ȡ�Ƽ��û��б�  (���redis��������)
                    String key = USER_CACHE_RECOMMEND_KEY + i;
                    ValueOperations<String,Object> valueOperations = redisTemplate.opsForValue();
                    try {
                        valueOperations.set(key, safetyUserListDO, 30, TimeUnit.MINUTES);//���ù���ʱ�䣡��
                    }catch (Exception e){
                        log.info("Ԥ�ȴ���",e.getMessage());
                    }
                }
            }
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }finally {
            //2.��֤�Լ��ͷ��Լ�����
            if (lock.isHeldByCurrentThread()){
                lock.unlock();
            }
        }
    }

    /**
     * ��ʱ����2 : ���ж����б�id ��Ӧ���е� �û�id�б�
     * ���浽����Map??������Ҫ����΢����??
     * Ԥ�ȵ��ٶ�Ҳ��Ҫ������ʱ������ʱ�䣡??
     */
//    @Scheduled(cron = "0 00 23 * * ?")//ÿ������17:15����
    public void doTeamIdToUserIdListMap(){
        //������֤�ֲ�ʽ����ʱֻ��һ����ɼ�??
        RLock lock = redissonClient.getLock(USER_LOCK_JOB_TEAM_USER_MAP_KEY);
        try {
            //1.��ֻ֤��һ���߳��õ���
            if(lock.tryLock(0,30000L,TimeUnit.MILLISECONDS)){
                List<UserTeamDO> userTeamDOList = userTeamMapper.selectList(new QueryWrapper<UserTeamDO>().select("teamId", "userId"));
                Map<Long, Set<Long>> teamIdUserIdMap = userTeamDOList.stream().collect(Collectors.groupingBy(UserTeamDO::getTeamId, Collectors.mapping(UserTeamDO::getUserId, Collectors.toSet())));
                ID_TEAM_MAP.clear();
                ID_TEAM_MAP.putAll(teamIdUserIdMap);
            }
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }finally {
            //2.��֤�Լ��ͷ��Լ�����
            if (lock.isHeldByCurrentThread()){
                lock.unlock();
            }
        }
    }

}
